/**
 * request 网络请求工具
 * 更详细的 api 文档: https://github.com/umijs/umi-request
 */
import { notification } from 'antd';
import request, { extend } from 'umi-request';

import { DEFAULT_API_HOST } from '@/appConfig';

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};
/**
 * 异常处理程序
 */

const errorHandler = (error) => {
  const { response } = error;
  let errorText = '';
  let resStatus = 0;

  if (response && response.status) {
    const errorDesc = codeMessage[response.status] || response.statusText;
    const { status, url } = response;
    resStatus = response.status;
    errorText = `请求错误 ${status}: ${errorDesc} ${url}`;
  } else if (!response) {
    errorText = `未知异常: ${error}`;
  }

  notification.error({
    message: `系统异常(${error.request?.url})`,
    description: errorText,
    placement: 'top',
    duration: 5,
  });

  return {
    success: false,
    result: response,
    error: { code: resStatus, message: errorText },
  };
};

const shouldCache = new Map();
const TTL = 300 * 1000;

export const isVoid = (value) =>
  value === undefined || value === null || value === '';

export const cleanObject = (obj) => {
  const result = { ...obj };
  Object.keys(result).forEach((key) => {
    const value = result[key];
    if (isVoid(value)) {
      delete result[key];
    }
  });
  return result;
};

/**
 * 通过拦截器添加默认缓存
 */
request.interceptors.request.use(
  (url, { host = DEFAULT_API_HOST, headers, ...options }) => {
    if (process.env.NODE_ENV === 'development') {
      //host = 'https://zapi.in.zhihu.com/mock/4493'
    }
    let query = '';
    const params = options.params;
    if (Object.keys(cleanObject(params)).length) {
      const formatQuery = Object.keys(cleanObject(params))
        .map((p) => `${p}=${params[p]}`)
        .join('&');
      if (`${host}${url}`.indexOf('?') !== -1) {
        query = `&${formatQuery}`;
      } else {
        query = `?${formatQuery}`;
      }
    }
    const reqStr = `${host}${url}${query}`;
    const shouldCacheData = shouldCache.get(reqStr);
    let useCache = false;
    if (
      shouldCacheData &&
      Date.now() - shouldCacheData.cacheTime <= TTL &&
      options.method.toLowerCase() === 'get'
    ) {
      useCache = true;
    }
    return {
      url: `${host}${url}`,
      options: {
        ttl: TTL,
        maxCache: 0,
        useCache,
        errorHandler,
        ...options,
        headers: {
          ...headers,
          'X-Requested-With': 'Fetch',
        },
      },
    };
  },
);

request.interceptors.response.use(async (response) => {
  const resp = await response.clone().json();
  if (!resp.success && !resp.isSuccess && resp.status !== 0) {
    notification.error({
      message: `请求失败(${response.url})`,
      description: resp.msg,
      placement: 'top',
      duration: 5,
    });
  } else {
    shouldCache.set(response.url, {
      cacheTime: Date.now(),
    });
  }
  return response;
});

export const requestWithoutCache = extend({ useCache: false });

export default request;
